[2024年版]GuardDutyで様々な検出を発生させるAmazon GuardDuty Testerを簡単に実行できるようにアレンジしてみた

[2024年版]GuardDutyで様々な検出を発生させるAmazon GuardDuty Testerを簡単に実行できるようにアレンジしてみた

Amazon GuardDuty Testerが2024年に波乱の人生を迎えていました。現在でも簡単に利用するための方法を考えました。
Clock Icon2024.09.16

こんにちは、臼田です。

みなさん、GuardDutyで遊んでますか?(挨拶

今回はGuardDutyにいろんな脅威を検出させることができるAmazon GuardDuty Testerを使ってみたのですが、2024年になり色々変わっていたので、簡単に利用できるようにしてみました。

Amazon GuardDuty Testerの2024年の状況

Amazon GuardDuty Testerは2018年ごろからawslabsで公開されているリポジトリです。以前からやってみた記事は以下のようにいろいろあります。

https://dev.classmethod.jp/articles/amazon-guardduty-tester-findings/

しかし現在のリポジトリは以前の状態から変わっています。amazon-guardduty-testerのリポジトリは今、以下のように表示されています。

001_guardduty_tester_2024

残念ながら2024年8月にこのリポジトリはアーカイブされていました。もちろん引き続きツールを利用することはできます。

しかし、もう1つ以前から変わっているところがあります。以下のデプロイ方法を確認してください。

002_guardduty_tester_2024

デプロイ方法がCDKを利用する方法に変わっています。これは2024年6月に変更されました。ついでにいろんなGuardDuty Findingsも検出できるようになりました。ちなみにその際にツールの名前もAmazon GuardDuty TesterからGuardDuty Findings Testerに変わっていました。

以前のデプロイは以下のようにCloudFormationテンプレートを使ってデプロイする方式でした。

003_guardduty_tester_2024

CDKで展開するのもよいですが、環境の準備が必要になります。

試しにCloudShellの環境から実行してみたのですが、ストレージ容量の問題でデプロイできませんでした。そのため、どのような環境でもお手軽に実行できなくなってしまいました。

というわけで、今回は以前の方式に戻して、CloudFormationテンプレートで展開できるようにしてみます。といっても、直近の変更でそのままテンプレートを利用するだけではうまく動かなくなっていたので、これをアレンジして共有します。

CloudFormationを利用してAmazon GuardDuty Testerを展開する(2024年版)

以前のGuardDuty TesterのテンプレートではセットアップされるEC2内で実行されるスクリプトなどは直接内包せず、GitHubのリポジトリ上にあるファイルを参照するようになっていました。これがmasterを指しているため、現状では利用できません。というわけで以下のように改変しました。(1000行近くあるので閉じておきます)

guardduty-tester-template.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  This template creates the basic VPC infrastructure for an isolated testing
  environment. It will deploy a bastion host into the public subnet for a single
  Availability Zone so we have a protected point of entry. It will then create a
  linux instance with some red team scripts & tools that operate against common
  applications that are created in the same private subnet. **WARNING** This
  template creates Amazon EC2 instance and related resources. You will be billed
  for the AWS resources used if you create a stack from this template.
Metadata:
  'AWS::CloudFormation::Interface':
    ParameterGroups:
      - Label:
          default: Network Configuration
        Parameters:
          - AvailabilityZones
          - VPCCIDR
          - PrivateSubnet1CIDR
          - PublicSubnet1CIDR
          - RemoteAccessCIDR
      - Label:
          default: Amazon EC2 Configuration
        Parameters:
          - KeyPairName
    ParameterLabels:
      AvailabilityZones:
        default: Availability Zones
      KeyPairName:
        default: Key Pair Name
      PrivateSubnetCIDR:
        default: Private Subnet CIDR
      PublicSubnetCIDR:
        default: Public Subnet CIDR
      RemoteAccessCIDR:
        default: Allowed Bastion External Access CIDR
      VPCCIDR:
        default: VPC CIDR
Parameters:
  AvailabilityZones:
    Description: >-
      Availability Zone to use for the subnets in the VPC. You can select many,
      but we just use 1 (the first).
    Type: 'List<AWS::EC2::AvailabilityZone::Name>'
  KeyPairName:
    Description: >-
      Public/private key pairs allow you to securely connect to your instance
      after it launches
    Type: 'AWS::EC2::KeyPair::KeyName'
  PrivateSubnetCIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 172.16.0.16/28
    Description: CIDR block for isolated private subnet.
    Type: String
  PublicSubnetCIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 172.16.0.0/28
    Description: CIDR Block for the public DMZ subnet for secure administrative entry
    Type: String
  RemoteAccessCIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
    Default: 0.0.0.0/0
    Description: CIDR from which access to bastion is to be permitted
    Type: String
  VPCCIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 172.16.0.0/27
    Description: CIDR Block for the VPC
    Type: String
  LatestLinuxAMI:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
  LatestWindows2022AMI:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: >-
      /aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base
  LatestECSOptimizedAMI:
    Description: AMI ID
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id
Conditions:
  NVirginiaRegionCondition: !Equals 
    - !Ref 'AWS::Region'
    - us-east-1

Resources:
  BastionMainLogGroup:
    Type: 'AWS::Logs::LogGroup'
  SSHMetricFilter:
    Type: 'AWS::Logs::MetricFilter'
    Properties:
      LogGroupName: !Ref BastionMainLogGroup
      FilterPattern: ON FROM USER PWD
      MetricTransformations:
        - MetricName: SSHCommandCount
          MetricValue: 1
          MetricNamespace: !Join 
            - /
            - - AWSQuickStart
              - !Ref 'AWS::StackName'

  DHCPOptions:
    Type: 'AWS::EC2::DHCPOptions'
    Properties:
      DomainName: !If 
        - NVirginiaRegionCondition
        - ec2.internal
        - !Join 
          - ''
          - - !Ref 'AWS::Region'
            - .compute.internal
      DomainNameServers:
        - AmazonProvidedDNS

  VPC:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: !Ref VPCCIDR
      InstanceTenancy: default
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      Tags:
        - Key: Name
          Value: !Ref 'AWS::StackName'
        - Key: CreatedBy
          Value: GuardDuty Test Script

  VPCDHCPOptionsAssociation:
    Type: 'AWS::EC2::VPCDHCPOptionsAssociation'
    Properties:
      VpcId: !Ref VPC
      DhcpOptionsId: !Ref DHCPOptions

  InternetGateway:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
        - Key: Network
          Value: Public

  VPCGatewayAttachment:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PrivateSubnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnetCIDR
      AvailabilityZone: !Select 
        - '0'
        - !Ref AvailabilityZones
      Tags:
        - Key: Name
          Value: Private subnet
        - Key: Network
          Value: Private
        - Key: CreatedBy
          Value: GuardDuty Test Script

  PublicSubnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnetCIDR
      AvailabilityZone: !Select 
        - '0'
        - !Ref AvailabilityZones
      Tags:
        - Key: Name
          Value: Public subnet
        - Key: Network
          Value: Public
        - Key: CreatedBy
          Value: GuardDuty Test Script
      MapPublicIpOnLaunch: true

  PrivateSubnetRouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Private subnet
        - Key: Network
          Value: Private

  PrivateSubnetRoute:
    Type: 'AWS::EC2::Route'
    Properties:
      RouteTableId: !Ref PrivateSubnetRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NATGateway

  PrivateSubnetRouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateSubnetRouteTable

  PublicSubnetRouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Public Subnets
        - Key: Network
          Value: Public

  PublicSubnetRoute:
    DependsOn: VPCGatewayAttachment
    Type: 'AWS::EC2::Route'
    Properties:
      RouteTableId: !Ref PublicSubnetRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicSubnetRouteTable

  NATEIP:
    DependsOn: VPCGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  NATGateway:
    DependsOn: VPCGatewayAttachment
    Type: 'AWS::EC2::NatGateway'
    Properties:
      AllocationId: !GetAtt 
        - NATEIP
        - AllocationId
      SubnetId: !Ref PublicSubnet

  BastionHostRole:
    Type: 'AWS::IAM::Role'
    Properties:
      Policies:
        - PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - 'logs:CreateLogStream'
                  - 'logs:GetLogEvents'
                  - 'logs:PutLogEvents'
                  - 'logs:DescribeLogGroups'
                  - 'logs:DescribeLogStreams'
                  - 'logs:PutRetentionPolicy'
                  - 'logs:PutMetricFilter'
                  - 'logs:CreateLogGroup'
                Resource:
                  !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${BastionMainLogGroup}:*"
                Effect: Allow
          PolicyName: bastion-cloudwatch-logs-policy
        - PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - 'ec2:AssociateAddress'
                  - 'ec2:DescribeAddresses'
                Resource:
                  - '*'
                Effect: Allow
          PolicyName: bastion-eip-policy
      Path: /
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Principal:
              Service:
                - ec2.amazonaws.com
            Effect: Allow
        Version: 2012-10-17

  BastionHostProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Roles:
        - !Ref BastionHostRole
      Path: /
  EIP:
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  BastionAutoScalingGroup:
    Type: 'AWS::AutoScaling::AutoScalingGroup'
    Properties:
      LaunchTemplate:
         LaunchTemplateId: !Ref BastionLaunchTemplate
         Version: !GetAtt BastionLaunchTemplate.LatestVersionNumber
      VPCZoneIdentifier:
        - !Ref PublicSubnet
      MinSize: '1'
      MaxSize: '2'
      Cooldown: '300'
      DesiredCapacity: '1'
      Tags:
        - Key: Name
          Value: LinuxBastion
          PropagateAtLaunch: 'true'
        - Key: CreatedBy
          Value: GuardDuty Test Script
          PropagateAtLaunch: 'true'
    CreationPolicy:
      ResourceSignal:
        Count: '1'
        Timeout: PT30M

  BastionLaunchTemplate:
    Type: 'AWS::EC2::LaunchTemplate'
    Properties:
      LaunchTemplateName: Bastion-Launch-Template
      LaunchTemplateData:
        KeyName: !Ref KeyPairName
        IamInstanceProfile: 
          Name: !Ref BastionHostProfile
        ImageId: !Ref LatestLinuxAMI
        SecurityGroupIds:
          - !Ref BastionSecurityGroup
        InstanceType: t3.micro
        UserData: !Base64 
          'Fn::Join':
            - ''
            - - |
                #!/bin/bash
              - |
                export PATH=$PATH:/usr/local/bin
              - |
                yum update -y
              - |
                yum install nmap -y
              - >
                yum install -y aws-cfn-bootstrap
              - >
                curl -L -o /tmp/bastion_bootstrap.sh
                https://raw.githubusercontent.com/awslabs/amazon-guardduty-tester/68854573557ede4cc36047361fa04c6447e20e58/bastion_bootstrap.sh
              - |
                chown root: /tmp/bastion_bootstrap.sh
              - |
                chmod +x /tmp/bastion_bootstrap.sh
              - EIP_LIST="
              - !Ref EIP
              - ',Null,Null,Null'
              - |
                "
              - CLOUDWATCHGROUP=
              - !Ref BastionMainLogGroup
              - |+

              - /tmp/bastion_bootstrap.sh
              - ' --banner '
              - >-
                https://raw.githubusercontent.com/awslabs/amazon-guardduty-tester/68854573557ede4cc36047361fa04c6447e20e58/artifacts/banner_message.txt
              - ' --enable true'
              - ' --tcp-forwarding true'
              - ' --x11-forwarding false'
              - |+

              - '/opt/aws/bin/cfn-signal -e $? --stack '
              - !Ref 'AWS::StackName'
              - ' --resource BastionAutoScalingGroup --region '
              - !Ref 'AWS::Region'
              - |+

  BastionSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Enables SSH Access to Bastion Hosts
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: !Ref RemoteAccessCIDR

  RedTeamECSCluster:
    Type: 'AWS::ECS::Cluster'
  CloudwatchLogsGroup:
    Type: 'AWS::Logs::LogGroup'
    Properties:
      LogGroupName: !Join 
        - '-'
        - - ECSLogGroup
          - !Ref 'AWS::StackName'
      RetentionInDays: 14

  taskdefinition:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      Family: !Join 
        - ''
        - - !Ref 'AWS::StackName'
          - '-ecs-demo-app'
      ContainerDefinitions:
        - Name: simple-app
          Cpu: '10'
          Essential: 'true'
          Image: 'httpd:2.4'
          Memory: '300'
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref CloudwatchLogsGroup
              awslogs-region: !Ref 'AWS::Region'
              awslogs-stream-prefix: ecs-demo-app
          PortMappings:
            - ContainerPort: 80
          Command:
            - >-
              /bin/sh -c "apt update -y && apt install zip -y && echo -n 'X5O!P%@AP[4\PZX54(P^)7CC)7}\$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!\$H+H*' >/tmp/eicar.com && cp /tmp/eicar.com /tmp/eicar.com.txt && zip -j /tmp/eicar_com.zip /tmp/eicar.com && zip -j /tmp/eicarcom2.zip /tmp/eicar_com.zip && sleep infinity"
          EntryPoint:
            - sh
            - '-c'

  ECSAutoScalingGroup:
    Type: 'AWS::AutoScaling::AutoScalingGroup'
    Properties:
      VPCZoneIdentifier: 
        - !Ref PrivateSubnet
      LaunchTemplate:
         LaunchTemplateId: !Ref ContainerInstances
         Version: !GetAtt ContainerInstances.LatestVersionNumber
      MinSize: '1'
      MaxSize: '1'
      DesiredCapacity: '1'
      Tags:
        - Key: Name
          Value: RedTeam
          PropagateAtLaunch: "true"
        - Key: CreatedBy
          Value: GuardDuty Test Script
          PropagateAtLaunch: "true"
    CreationPolicy:
      ResourceSignal:
        Timeout: PT15M
    UpdatePolicy:
      AutoScalingReplacingUpdate:
        WillReplace: 'true'

  ContainerInstances:
    Type: 'AWS::EC2::LaunchTemplate'
    DependsOn:
      - BasicLinuxTarget
      - BasicWindowsTarget
      - NATGateway
    Properties:
      LaunchTemplateName: ContainerInstances-Launch-Template
      LaunchTemplateData:
        ImageId: !Ref LatestECSOptimizedAMI
        SecurityGroupIds:
          - !Ref RedTeamSecurityGroup
        InstanceType: t3.micro
        IamInstanceProfile: 
          Name: !Ref RedTeamEC2InstanceProfile
        KeyName: !Ref KeyPairName
        UserData: !Base64 
          'Fn::Join':
            - ''
            - - |
                #!/bin/bash -xe
              - echo ECS_CLUSTER=
              - !Ref RedTeamECSCluster
              - |2
                 >> /etc/ecs/ecs.config
              - |
                export PATH=$PATH:/usr/local/bin:/usr/sbin:/root/.local/bin
              - >
                echo 'export PATH=/root/.local/bin:/usr/sbin:$PATH' >>
                /home/ec2-user/.profile
              - |
                yum update -y
              - >
                yum install nmap git python3 python-argparse
                gcc gcc-c++ glib2-devel bind-utils wget unzip -y
              - >
                yum install cmake openssl-devel libX11-devel libXi-devel
                libXtst-devel libXinerama-devel libusb-static libusbmuxd-devel
                libusbx-devel libusb-devel -y
              - |
                yum install freerdp freerdp-devel desktop-file-utils -y
              - |
              - |
                pip3 install paramiko
              - |
                TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
              - >
                export privateIP=`curl -H "X-aws-ec2-metadata-token: $TOKEN"
                -v http://169.254.169.254/latest/meta-data/local-ipv4`
              - >
                curl -L
                https://raw.githubusercontent.com/awslabs/amazon-guardduty-tester/68854573557ede4cc36047361fa04c6447e20e58//guardduty_tester.sh
                > /home/ec2-user/guardduty_tester.sh
              - >
                mkdir /home/ec2-user/compromised_keys
                /home/ec2-user/domains
                /home/ec2-user/passwords
              - >
                curl -L
                https://raw.githubusercontent.com/awslabs/amazon-guardduty-tester/68854573557ede4cc36047361fa04c6447e20e58//artifacts/queries.txt
                > /home/ec2-user/domains/queries.txt
              - >
                curl -L
                https://raw.githubusercontent.com/awslabs/amazon-guardduty-tester/68854573557ede4cc36047361fa04c6447e20e58//artifacts/password_list.txt
                > /home/ec2-user/passwords/password_list.txt
              - >
                curl -L
                https://raw.githubusercontent.com/awslabs/amazon-guardduty-tester/68854573557ede4cc36047361fa04c6447e20e58//artifacts/never_used_sample_key.foo
                > /home/ec2-user/compromised_keys/compromised.pem
              - |
                FILE="/home/ec2-user/compromised_keys/compromised.pem"
              - >
                for FILE in {1..20}; do cp
                /home/ec2-user/compromised_keys/compromised.pem
                /home/ec2-user/compromised_keys/compromised$FILE.pem; done
              - echo 'BASIC_LINUX_TARGET="
              - !GetAtt 
                - BasicLinuxTarget
                - PrivateIp
              - |
                "' >> /home/ec2-user/localIps.sh
              - echo 'BASIC_WINDOWS_TARGET="
              - !GetAtt 
                - BasicWindowsTarget
                - PrivateIp
              - |
                "' >> /home/ec2-user/localIps.sh
              - |
                echo -n 'RED_TEAM_INSTANCE="' >> /home/ec2-user/localIps.sh
              - >
                curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/instance-id
                >> /home/ec2-user/localIps.sh
              - |
                echo '"' >> /home/ec2-user/localIps.sh
              - |
                echo -n 'RED_TEAM_IP="' >> /home/ec2-user/localIps.sh
              - >
                curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/local-ipv4 >>
                /home/ec2-user/localIps.sh
              - |
                echo '"' >> /home/ec2-user/localIps.sh
              - echo 'BASIC_LINUX_INSTANCE="
              - !Ref BasicLinuxTarget
              - |
                "' >> /home/ec2-user/localIps.sh
              - echo 'BASIC_WINDOWS_INSTANCE="
              - !Ref BasicWindowsTarget
              - |
                "' >> /home/ec2-user/localIps.sh
              - |
                cd /home/ec2-user/
              - |
                cat << EOF >> users
              - |
                ec2-user
                root
                admin
                administrator
                ftp
                www
                nobody
                EOF
              - |
                pip3 install cmake
              - >
                wget https://github.com/vanhauser-thc/thc-hydra/archive/refs/tags/v9.4.zip 
                -P /home/ec2-user
              - >
                wget -q -O /home/ec2-user/libssh.tar.xz
                https://www.libssh.org/files/0.9/libssh-0.9.4.tar.xz
              - |
                tar -xvf /home/ec2-user/libssh.tar.xz
              - |
                cd /home/ec2-user/libssh-0.9.4
              - |
                mkdir build
              - |
                cd build
              - >
                cmake -DUNIT_TESTING=OFF -DCMAKE_INSTALL_PREFIX=/usr
                -DCMAKE_BUILD_TYPE=Release ..
              - |
                make && make install
              - |
                cd /home/ec2-user
              - |
                unzip v9.4.zip
              - |
                cd /home/ec2-user/thc-hydra-9.4
              - |
                /home/ec2-user/thc-hydra-9.4/configure
              - |
                make
              - |
                make install
              - |
                git clone https://github.com/galkan/crowbar /home/ec2-user/crowbar
              - |
                chown -R ec2-user: /home/ec2-user
              - |
                chmod +x /home/ec2-user/guardduty_tester.sh
              - |
                chmod +x /home/ec2-user/crowbar/crowbar.py
              - |
                cd /home/ec2-user
              - |
                wget https://secure.eicar.org/eicar.com
              - |
                wget https://secure.eicar.org/eicar.com.txt
              - |
                wget https://secure.eicar.org/eicar_com.zip
              - |
                wget https://secure.eicar.org/eicarcom2.zip
              - |
                # Signal the status from cfn-init
                yum install -y aws-cfn-bootstrap
              - '/opt/aws/bin/cfn-signal -e $? '
              - '         --stack '
              - !Ref 'AWS::StackName'
              - '         --resource ECSAutoScalingGroup '
              - '         --region '
              - !Ref 'AWS::Region'
              - |+

  service:
    Type: 'AWS::ECS::Service'
    Properties:
      Cluster: !Ref RedTeamECSCluster
      DesiredCount: '1'
      TaskDefinition: !Ref taskdefinition

  ServiceScalingTarget:
    Type: 'AWS::ApplicationAutoScaling::ScalableTarget'
    DependsOn: service
    Properties:
      MaxCapacity: 2
      MinCapacity: 1
      ResourceId: !Join 
        - ''
        - - service/
          - !Ref RedTeamECSCluster
          - /
          - !GetAtt 
            - service
            - Name
      RoleARN: !GetAtt 
        - AutoscalingRole
        - Arn
      ScalableDimension: 'ecs:service:DesiredCount'
      ServiceNamespace: ecs

  ServiceScalingPolicy:
    Type: 'AWS::ApplicationAutoScaling::ScalingPolicy'
    Properties:
      PolicyName: AStepPolicy
      PolicyType: StepScaling
      ScalingTargetId: !Ref ServiceScalingTarget
      StepScalingPolicyConfiguration:
        AdjustmentType: PercentChangeInCapacity
        Cooldown: 60
        MetricAggregationType: Average
        StepAdjustments:
          - MetricIntervalLowerBound: 0
            ScalingAdjustment: 200

  RedTeamEC2Role:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: ecs-service
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - 'ecs:CreateCluster'
                  - 'ecs:DeregisterContainerInstance'
                  - 'ecs:DiscoverPollEndpoint'
                  - 'ecs:Poll'
                  - 'ecs:RegisterContainerInstance'
                  - 'ecs:StartTelemetrySession'
                  - 'ecs:Submit*'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: '*'

  AutoscalingRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - application-autoscaling.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: service-autoscaling
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - 'application-autoscaling:*'
                  - 'cloudwatch:DescribeAlarms'
                  - 'cloudwatch:PutMetricAlarm'
                  - 'ecs:DescribeServices'
                  - 'ecs:UpdateService'
                Resource: '*'

  RedTeamEC2InstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Path: /
      Roles:
        - !Ref RedTeamEC2Role

  RedTeamSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Enables SSH Access to RedTeam Tools Host
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          SourceSecurityGroupId: !Ref BastionSecurityGroup
        - IpProtocol: tcp
          FromPort: '53'
          ToPort: '53'
          CidrIp: !Ref PrivateSubnetCIDR
        - IpProtocol: udp
          FromPort: '53'
          ToPort: '53'
          CidrIp: !Ref PrivateSubnetCIDR
        - IpProtocol: tcp
          FromPort: '5050'
          ToPort: '5050'
          CidrIp: !Ref PrivateSubnetCIDR
        - IpProtocol: icmp
          FromPort: '-1'
          ToPort: '-1'
          SourceSecurityGroupId: !Ref BastionSecurityGroup

  BasicLinuxNetInt:
    Type: 'AWS::EC2::NetworkInterface'
    Properties:
      SubnetId: !Ref PrivateSubnet
      GroupSet:
        - !Ref BasicLinuxSecurityGroup

  BasicLinuxSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Enables Admin Access to basic linux hosts
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          SourceSecurityGroupId: !Ref RedTeamSecurityGroup
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          SourceSecurityGroupId: !Ref RedTeamSecurityGroup
        - IpProtocol: tcp
          FromPort: '5050'
          ToPort: '5050'
          SourceSecurityGroupId: !Ref RedTeamSecurityGroup
        - IpProtocol: icmp
          FromPort: '-1'
          ToPort: '-1'
          SourceSecurityGroupId: !Ref RedTeamSecurityGroup

  BasicLinuxIAMRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess'

  BasicLinuxInstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Roles:
        - !Ref BasicLinuxIAMRole
      Path: /

  BasicLinuxTarget:
    Type: 'AWS::EC2::Instance'
    Properties:
      KeyName: !Ref KeyPairName
      NetworkInterfaces:
        - NetworkInterfaceId: !Ref BasicLinuxNetInt
          DeviceIndex: '0'
      IamInstanceProfile: !Ref BasicLinuxInstanceProfile
      UserData: !Base64 
        'Fn::Join':
          - ''
          - - |
              #!/bin/bash
            - |
              export PATH=$PATH:/usr/local/bin
            - |
              yum update -y
            - >
              yum install -y httpd24 php70 mysql56-server php70-mysqlnd gcc
              openssl-devel* nmap
            - |
              service httpd start
            - >
              export LOCAL_HOST=`curl
              http://169.254.169.254/latest/meta-data/local-hostname`
            - >
              wget -O /home/ec2-user/install
              https://d1wk0tztpsntt1.cloudfront.net/linux/latest/install
            - |
              chmod +x /home/ec2-user/install
            - |
              bash /home/ec2-user/install -u false
      InstanceType: t3.micro
      AvailabilityZone: !Select 
        - '0'
        - !Ref AvailabilityZones
      ImageId: !Ref LatestLinuxAMI
      Tags:
        - Key: Name
          Value: BasicLinuxTarget
        - Key: CreatedBy
          Value: GuardDuty Test Script

  BasicWindowsSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Enables Admin Access to basic windows hosts
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '3389'
          ToPort: '3389'
          SourceSecurityGroupId: !Ref RedTeamSecurityGroup
        - IpProtocol: icmp
          FromPort: '-1'
          ToPort: '-1'
          SourceSecurityGroupId: !Ref RedTeamSecurityGroup

  BasicWindowsIAMRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /

  BasicWindowsInstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Roles:
        - !Ref BasicWindowsIAMRole
      Path: /

  BasicWindowsTarget:
    Type: 'AWS::EC2::Instance'
    Properties:
      KeyName: !Ref KeyPairName
      NetworkInterfaces:
        - GroupSet:
            - !Ref BasicWindowsSecurityGroup
          AssociatePublicIpAddress: 'false'
          DeviceIndex: '0'
          DeleteOnTermination: 'true'
          SubnetId: !Ref PrivateSubnet
      InstanceType: t3.micro
      AvailabilityZone: !Select 
        - '0'
        - !Ref AvailabilityZones
      ImageId: !Ref LatestWindows2022AMI
      Tags:
        - Key: Name
          Value: BasicWindowsTarget
        - Key: CreatedBy
          Value: GuardDuty Test Script

Outputs:
  BastionIp:
    Description: Elastic IP for Bastion
    Value: !Ref EIP

最後の変更前のコミットを参照するように変更しました。

後は適当にこれでCloudFormationスタックを作成することで展開できます。展開したら複数のEC2が作成されますが、RedTeamインスタンスに接続します。外部からSSHで接続する場合にはBastion経由になりますが、以下記事のようなDHMCがあればSession Managerが利用できます。

https://dev.classmethod.jp/articles/aws-systems-manager-supports-default-host-management-configuration/

接続しましょう。

004_guardduty_tester_2024

Session Managerの場合にはec2-userではないため、sudo su - ec2-userしてから、実際にGuardDuty Testerを動かす./guardduty_tester.shを実行します。

005_guardduty_tester_2024

しばらくすると、GuardDutyが脅威を検出してFindingsが生成されます。

006_guardduty_tester_2024

まとめ

GuardDuty Testerを2024年でも簡単に利用できるようにしてみました。もちろんCDKが利用できる環境であれば、新しいFindingタイプも含めて利用できますのでそちらもおすすめです。

しかしながら、環境依存少なく実行したい場合などはこちらの方法も便利ですので検討してみてください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.